package com.swak.utils.ring;

import java.util.Arrays;

import com.swak.utils.Ints;
import com.swak.utils.UNSAFE;

import sun.misc.Unsafe;

/**
 * 仿照 LMAX.
 * 
 * @author 618lf
 */
@SuppressWarnings("unchecked")
public abstract class AbstractRingBuffer<E> {

	private static final int BUFFER_PAD;
	private static final long REF_ARRAY_BASE;
	private static final int REF_ELEMENT_SHIFT;
	private static final Unsafe unsafe = UNSAFE.getUnsafe();

	static {
		final int scale = unsafe.arrayIndexScale(Object[].class);
		if (4 == scale) {
			REF_ELEMENT_SHIFT = 2;
		} else if (8 == scale) {
			REF_ELEMENT_SHIFT = 3;
		} else {
			throw new IllegalStateException("Unknown pointer size");
		}
		BUFFER_PAD = 128 / scale;
		// Including the buffer pad in the array base offset
		REF_ARRAY_BASE = unsafe.arrayBaseOffset(Object[].class) + (BUFFER_PAD << REF_ELEMENT_SHIFT);
	}

	protected final long indexMask;
	private final Object[] entries;
	protected final int bufferSize;

	public AbstractRingBuffer(int bufferSize) {

		// pow of 2
		this.bufferSize = Ints.capacity(bufferSize);
		this.indexMask = this.bufferSize - 1;
		this.entries = new Object[this.bufferSize + 2 * BUFFER_PAD];
		for (int i = 0; i < this.bufferSize; i++) {
			entries[BUFFER_PAD + i] = this.newInstance();
		}
	}

	/**
	 * 创建数据
	 * 
	 * @return
	 */
	protected abstract E newInstance();

	/**
	 * 存储的实际的数据
	 * 
	 * for test;
	 * 
	 * @return
	 */
	protected Object[] entries() {
		return Arrays.copyOf(this.entries, this.entries.length);
	}

	/**
	 * 获得数据
	 * 
	 * @param sequence
	 * @return
	 */
	protected final E elementAt(long sequence) {
		return (E) unsafe.getObject(entries, REF_ARRAY_BASE + ((sequence & indexMask) << REF_ELEMENT_SHIFT));
	}
}